package com.vrsys.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.ibatis.io.Resources;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*
 * spring bean, scope: singleton
 */
public class IDGenerator {
    private int orderId = 0;
    private int lineId = 0;
    private int productId = 0;
    private int coupon4UserId = 0;
    private ReentrantLock lock = new ReentrantLock();
    private ReentrantLock lock1 = new ReentrantLock();
    private ReentrantLock lock2 = new ReentrantLock();
    private ReentrantLock lock3 = new ReentrantLock();
    private String idStorePropertiesFile;
    private Logger logger = LoggerFactory.getLogger(IDGenerator.class);

    public IDGenerator() {
    }

    public IDGenerator(String idStorePropertiesFile) throws IOException {
        this.idStorePropertiesFile = idStorePropertiesFile;
        loadIds();
    }

    private void loadIds() throws IOException {
        Properties prop = new Properties();
        try {
//            logger.info(this.getClass().getClassLoader().getResource("")+"");
            InputStream inputStream = new FileInputStream(new File(idStorePropertiesFile));
            prop.load(inputStream);
            if(null == prop.getProperty("orderId") || "".equals(prop.getProperty("orderId")))
                orderId = 0;
            else 
                orderId = Integer.valueOf(prop.getProperty("orderId"));

            if(null == prop.getProperty("lineId") || "".equals(prop.getProperty("lineId")))
                lineId = 0;
            else 
                lineId = Integer.valueOf(prop.getProperty("lineId"));

            if(null == prop.getProperty("productId") || "".equals(prop.getProperty("productId")))
                productId = 0;
            else 
                productId = Integer.valueOf(prop.getProperty("productId"));

            if(null == prop.getProperty("coupon4UserId") || "".equals(prop.getProperty("coupon4UserId")))
                coupon4UserId = 0;
            else 
                coupon4UserId = Integer.valueOf(prop.getProperty("coupon4UserId"));
            inputStream.close();
        } catch (IOException e) {
            logger.error(e.getMessage());
            throw e;
        }
    }

    public int getId(String type) throws Throwable {
        switch(type) {
            case "orderId":
                lock.lock();
                orderId++;
                lock.unlock();
                return orderId;
            case "lineId":
                lock1.lock();
                lineId++;
                lock1.unlock();
                return lineId;
            case "productId": 
                lock2.lock();
                productId++;
                lock2.unlock();
                return productId;
            case "coupon4UserId": 
                lock3.lock();
                coupon4UserId++;
                lock3.unlock();
                return coupon4UserId;
            default: throw new Throwable("illegal request");
        }
    }

    public void saveIds() throws Exception {
        Properties prop = new Properties();
        prop.setProperty("orderId", orderId + "");
        prop.setProperty("lineId", lineId + "");
        prop.setProperty("productId", productId + "");
        prop.setProperty("coupon4UserId", coupon4UserId + "");
//        logger.info(orderId + " , " + lineId + " , " + productId + " , " + coupon4UserId);
        FileWriter fw = new FileWriter(new File(this.idStorePropertiesFile));
        prop.store(fw, "ids from last time");
        fw.close();
    }

    /*
     * only for unit test
     */
    public static IDGenerator getInstance() throws IOException {
        return new IDGenerator(Resources.getResourceAsFile("idstore.properties").getAbsolutePath());
    }

    public String getIdStorePropertiesFile() {
        return idStorePropertiesFile;
    }

    public void setIdStorePropertiesFile(String idStorePropertiesFile) throws IOException {
        this.idStorePropertiesFile = idStorePropertiesFile;
        loadIds();
    }

    /*
     * used for validation while starting up
     */
    public int getOrderId() {
        return orderId;
    }

    public void setOrderId(int orderId) {
        this.orderId = orderId;
    }

    public int getLineId() {
        return lineId;
    }

    public void setLineId(int lineId) {
        this.lineId = lineId;
    }

    public int getProductId() {
        return productId;
    }

    public void setProductId(int productId) {
        this.productId = productId;
    }

    public int getCoupon4UserId() {
        return coupon4UserId;
    }

    public void setCoupon4UserId(int coupon4UserId) {
        this.coupon4UserId = coupon4UserId;
    }

}
